/************************************************************************
                                                                     
   Xceed Ultimate ListBox for Silverlight                                                                                                                                            
   Copyright (C) 2010 Xceed Software Inc.    
                                                                     
   This program is provided to you under the terms of the GNU General Public  
   License version 2 as published by the Free Software Foundation. 
        
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY, without even the implied warranty of 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along 
   with this program, if not, write to the Free Software Foundation, Inc., 
   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

   This program can be provided to you by Xceed Software Inc. under a
   proprietary commercial license agreement for use in non-Open Source
   projects. Visit Xceed.com to find the commercial edition of 
   Xceed Ultimate ListBox for Silverlight.                                    
                                                                      
 **********************************************************************/

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Xceed.Silverlight.ListBox
{
  public abstract class SpinnerBase : Control
  {
    protected SpinnerBase()
    {
    }

    #region HighlightBrush Property

    public static readonly DependencyProperty HighlightBrushProperty = DependencyProperty.Register(
      "HighlightBrush",
      typeof( Brush ),
      typeof( SpinnerBase ),
      new PropertyMetadata( null ) );

    public Brush HighlightBrush
    {
      get
      {
        return ( Brush )this.GetValue( SpinnerBase.HighlightBrushProperty );
      }
      set
      {
        this.SetValue( SpinnerBase.HighlightBrushProperty, value );
      }
    }

    #endregion

    #region ShadowBrush Property

    public static readonly DependencyProperty ShadowBrushProperty = DependencyProperty.Register(
      "ShadowBrush",
      typeof( Brush ),
      typeof( SpinnerBase ),
      new PropertyMetadata( null ) );

    public Brush ShadowBrush
    {
      get
      {
        return ( Brush )this.GetValue( SpinnerBase.ShadowBrushProperty );
      }
      set
      {
        this.SetValue( SpinnerBase.ShadowBrushProperty, value );
      }
    }

    #endregion

    #region Minimum Property

    public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register(
      "Minimum",
      typeof( double ),
      typeof( SpinnerBase ),
      new PropertyMetadata( 0d,
        new PropertyChangedCallback( SpinnerBase.OnMinimumChanged ) ) );

    public double Minimum
    {
      get
      {
        return ( double )this.GetValue( SpinnerBase.MinimumProperty );
      }
      set
      {
        this.SetValue( SpinnerBase.MinimumProperty, value );
      }
    }

    private static void OnMinimumChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
    {
      SpinnerBase spinner = sender as SpinnerBase;

      if( spinner == null )
        return;

      spinner.OnMinimumChanged( ( double )e.OldValue, ( double )e.NewValue );
    }

    #endregion

    #region Maximum Property

    public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(
      "Maximum",
      typeof( double ),
      typeof( SpinnerBase ),
      new PropertyMetadata( 1d,
        new PropertyChangedCallback( SpinnerBase.OnMaximumChanged ) ) );

    public double Maximum
    {
      get
      {
        return ( double )this.GetValue( SpinnerBase.MaximumProperty );
      }
      set
      {
        this.SetValue( SpinnerBase.MaximumProperty, value );
      }
    }

    private static void OnMaximumChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
    {
      SpinnerBase spinner = sender as SpinnerBase;

      if( spinner == null )
        return;

      spinner.OnMaximumChanged( ( double )e.OldValue, ( double )e.NewValue );
    }

    #endregion

    #region Value Property

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
      "Value",
      typeof( double ),
      typeof( SpinnerBase ),
      new PropertyMetadata( 0d,
        new PropertyChangedCallback( SpinnerBase.OnValueChanged ) ) );

    public double Value
    {
      get
      {
        return ( double )this.GetValue( SpinnerBase.ValueProperty );
      }
      set
      {
        this.SetValue( SpinnerBase.ValueProperty, value );
      }
    }

    private static void OnValueChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
    {
      SpinnerBase spinner = sender as SpinnerBase;

      if( spinner == null )
        return;

      spinner.OnValueChanged( ( double )e.OldValue, ( double )e.NewValue );
    }

    #endregion

    #region Ratio Property

    public static readonly DependencyProperty RatioProperty = DependencyProperty.Register(
      "Ratio",
      typeof( double ),
      typeof( SpinnerBase ),
      new PropertyMetadata( 0d ) );

    public double Ratio
    {
      get
      {
        return ( double )this.GetValue( SpinnerBase.RatioProperty );
      }
    }

    internal void SetRatio( double value )
    {
      this.SetValue( SpinnerBase.RatioProperty, value );
    }

    #endregion

    internal void OnMinimumChanged( double oldValue, double newValue )
    {
      double maximum = this.Maximum;

      if( maximum > newValue )
        this.SetRatio( ( this.Value - newValue ) / ( maximum - newValue ) );
    }

    internal void OnMaximumChanged( double oldValue, double newValue )
    {
      double minimum = this.Minimum;

      if( newValue > minimum )
        this.SetRatio( ( this.Value - minimum ) / ( newValue - minimum ) );
    }

    internal void OnValueChanged( double oldValue, double newValue )
    {
      double minimum = this.Minimum;
      double maximum = this.Maximum;

      if( maximum > minimum )
        this.SetRatio( ( newValue - minimum ) / ( maximum - minimum ) );
    }
  }
}
